package com.aims.server.service.impl;

import com.aims.api.entity.Account;
import com.aims.api.entity.query.AccountQuery;
import com.aims.common.model.PageResult;
import com.aims.server.dao.AccountDao;
import com.aims.server.service.AccountService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.RowBounds;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

/**
 * 账户服务实现类
 *
 * <p>依赖 DAO：AccountDao</p>
 * <p>支持逻辑删除（deleted字段）和乐观锁（version字段）</p>
 *
 * @author Generator
 * @since 2025-10-22
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class AccountServiceImpl implements AccountService {

    private final AccountDao accountDao;

    /**
     * 创建账户
     *
     * @param account 账户对象
     * @return 账户ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long create(Account account) {
        if (account == null) {
            throw new IllegalArgumentException("账户对象不能为空");
        }

        // 检查账户编号是否已存在
        if (account.getAccountNo() != null) {
            Account existing = accountDao.selectByAccountNo(account.getAccountNo());
            if (existing != null) {
                throw new IllegalArgumentException("账户编号已存在: " + account.getAccountNo());
            }
        }

        int rows = accountDao.insert(account);
        if (rows > 0) {
            log.debug("账户创建成功，ID: {}, 账户编号: {}", account.getId(), account.getAccountNo());
            return account.getId();
        }
        throw new RuntimeException("账户创建失败");
    }

    /**
     * 创建账户（仅非空字段）
     *
     * @param account 账户对象
     * @return 账户ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createSelective(Account account) {
        if (account == null) {
            throw new IllegalArgumentException("账户对象不能为空");
        }

        // 检查账户编号是否已存在
        if (account.getAccountNo() != null) {
            Account existing = accountDao.selectByAccountNo(account.getAccountNo());
            if (existing != null) {
                throw new IllegalArgumentException("账户编号已存在: " + account.getAccountNo());
            }
        }

        int rows = accountDao.insertSelective(account);
        if (rows > 0) {
            log.debug("账户创建成功（选择性），ID: {}, 账户编号: {}", account.getId(), account.getAccountNo());
            return account.getId();
        }
        throw new RuntimeException("账户创建失败");
    }

    /**
     * 批量创建账户
     *
     * @param accounts 账户列表
     * @return 影响行数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchCreate(List<Account> accounts) {
        if (CollectionUtils.isEmpty(accounts)) {
            throw new IllegalArgumentException("账户列表不能为空");
        }

        // 检查账户编号是否有重复
        for (Account account : accounts) {
            if (account.getAccountNo() != null) {
                Account existing = accountDao.selectByAccountNo(account.getAccountNo());
                if (existing != null) {
                    throw new IllegalArgumentException("账户编号已存在: " + account.getAccountNo());
                }
            }
        }

        int rows = accountDao.batchInsert(accounts);
        log.debug("批量创建账户完成，数量: {}, 影响行数: {}", accounts.size(), rows);
        return rows;
    }

    /**
     * 根据ID更新账户
     *
     * @param account 账户对象
     * @return 影响行数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateById(Account account) {
        if (account == null || account.getId() == null) {
            throw new IllegalArgumentException("账户对象或ID不能为空");
        }

        int rows = accountDao.updateById(account);
        log.debug("账户更新完成，ID: {}, 影响行数: {}", account.getId(), rows);
        return rows;
    }

    /**
     * 根据ID更新账户（仅非空字段）
     *
     * @param account 账户对象
     * @return 影响行数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateSelectiveById(Account account) {
        if (account == null || account.getId() == null) {
            throw new IllegalArgumentException("账户对象或ID不能为空");
        }

        int rows = accountDao.updateSelectiveById(account);
        log.debug("账户更新完成（选择性），ID: {}, 影响行数: {}", account.getId(), rows);
        return rows;
    }

    /**
     * 根据ID和版本号更新账户（乐观锁）
     *
     * @param account 账户对象
     * @return 影响行数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateByIdWithVersion(Account account) {
        if (account == null || account.getId() == null) {
            throw new IllegalArgumentException("账户对象或ID不能为空");
        }
        if (account.getVersion() == null) {
            throw new IllegalArgumentException("版本号不能为空");
        }

        int rows = accountDao.updateByIdWithVersion(account);
        if (rows == 0) {
            log.warn("账户更新失败（乐观锁），ID: {}, Version: {}", account.getId(), account.getVersion());
            throw new RuntimeException("账户更新失败，数据已被修改或不存在");
        }
        log.debug("账户更新成功（乐观锁），ID: {}, Old Version: {}", account.getId(), account.getVersion());
        return rows;
    }

    /**
     * 批量更新账户
     *
     * @param accounts 账户列表
     * @return 影响行数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchUpdate(List<Account> accounts) {
        if (CollectionUtils.isEmpty(accounts)) {
            throw new IllegalArgumentException("账户列表不能为空");
        }

        int rows = accountDao.batchUpdate(accounts);
        log.debug("批量更新账户完成，数量: {}, 影响行数: {}", accounts.size(), rows);
        return rows;
    }

    /**
     * 根据ID逻辑删除账户
     *
     * @param id 账户ID
     * @return 影响行数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteById(Serializable id) {
        if (id == null) {
            throw new IllegalArgumentException("账户ID不能为空");
        }

        int rows = accountDao.softDeleteById(id);
        log.debug("账户逻辑删除完成，ID: {}, 影响行数: {}", id, rows);
        return rows;
    }

    /**
     * 根据ID集合批量逻辑删除账户
     *
     * @param ids 账户ID集合
     * @return 影响行数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteByIds(Collection<? extends Serializable> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            throw new IllegalArgumentException("账户ID集合不能为空");
        }

        int rows = accountDao.deleteByIds(ids);
        log.debug("批量逻辑删除账户完成，数量: {}, 影响行数: {}", ids.size(), rows);
        return rows;
    }

    /**
     * 根据ID查询账户
     *
     * @param id 账户ID
     * @return 账户对象，不存在返回 null
     */
    @Override
    public Account getById(Serializable id) {
        if (id == null) {
            throw new IllegalArgumentException("账户ID不能为空");
        }

        return accountDao.selectById(id);
    }

    /**
     * 根据账户编号查询账户
     *
     * @param accountNo 账户编号
     * @return 账户对象，不存在返回 null
     */
    @Override
    public Account getByAccountNo(String accountNo) {
        if (accountNo == null || accountNo.trim().isEmpty()) {
            throw new IllegalArgumentException("账户编号不能为空");
        }

        return accountDao.selectByAccountNo(accountNo);
    }

    /**
     * 根据条件查询账户列表
     *
     * @param query 查询条件
     * @return 账户列表
     */
    @Override
    public List<Account> listByCondition(AccountQuery query) {
        if (query == null) {
            query = new AccountQuery();
        }

        return accountDao.listByCondition(query);
    }

    /**
     * 根据条件统计账户数量
     *
     * @param query 查询条件
     * @return 账户数量
     */
    @Override
    public long countByCondition(AccountQuery query) {
        if (query == null) {
            query = new AccountQuery();
        }

        return accountDao.countByCondition(query);
    }

    /**
     * 分页查询账户
     *
     * @param query    查询条件
     * @param pageNo   页码（从1开始）
     * @param pageSize 每页大小
     * @return 分页结果
     */
    @Override
    public PageResult<Account> page(AccountQuery query, int pageNo, int pageSize) {
        if (pageNo < 1) {
            throw new IllegalArgumentException("页码必须大于0");
        }
        if (pageSize < 1 || pageSize > 1000) {
            throw new IllegalArgumentException("每页大小必须在1-1000之间");
        }
        if (query == null) {
            query = new AccountQuery();
        }

        // 使用 RowBounds 进行分页
        int offset = (pageNo - 1) * pageSize;
        RowBounds rowBounds = new RowBounds(offset, pageSize);

        // 查询数据
        List<Account> records = accountDao.listByCondition(query, rowBounds);

        // 查询总数
        long total = accountDao.countByCondition(query);

        return PageResult.of(records, total, (long) pageNo, (long) pageSize);
    }
}